package com.hxxy.wyp.petsLover.utils;

import com.hxxy.wyp.petsLover.common.entities.User;
import com.hxxy.wyp.petsLover.exception.AppException;
import com.hxxy.wyp.petsLover.security.SecurityContext;
import org.apache.commons.beanutils.NestedNullException;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.InvocationTargetException;
import java.util.Objects;
import java.util.ResourceBundle;
import java.util.regex.Pattern;

/**
 * @ClassName ValidatedUtils
 * @Description TODO
 * @Author wyp
 * @Date 2023/1/2 20:46
 * @Version 1.0
 */
public class ValidatedUtils {
    @Autowired
    public SecurityContext securityContext;
    /**
     * error message keys constants
     */
    public static final String ERROR_INVALID_DATA = "global.invalid.data";
    public static final String ERROR_INVALID_OPERATION = "global.invalid.operation";
    public static final String ERROR_ACCESS_DENIED = "global.access.denied";
    /**
     * string resources
     */
    public static final ResourceBundle RES = ResourceBundle.getBundle("strings/services");

    /**
     * validate string length
     *
     * @param value  value
     * @param length max length
     */
    public static void validateLength(Object value, int length, String error) {
        if (value == null || !value.getClass().equals(String.class))
            return;
        if (((String) value).length() > length)
            throw new AppException(error);
    }

    public static void validatePhone(Object value, int length, String error) {
        if (value == null || !value.getClass().equals(String.class))
            return;
        if (((String) value).length() != length) {
            throw new AppException(error);
        }
    }

    /**
     * validate password length
     *
     * @param value
     * @param length
     * @param error
     */
    public static void validatePassword(Object value, int length, String error) {
        if (value == null || !value.getClass().equals(String.class))
            return;
        if (((String) value).length() < length) {
            throw new AppException(error);
        }
    }

    /**
     * validate email @
     *
     * @param value
     * @param error
     */
    public static void validateEmail(Object value, String error) {
        if (value == null || !value.getClass().equals(String.class))
            return;
        if (!((String) value).contains("@")) {
            throw new AppException(error);
        }
    }

    /**
     * validate not null
     *
     * @param value value to validate
     */
    public static void validateNotNull(Object value) {
        validateNotNull(value, RES.getString("global.validation.not.null"));
    }

    /**
     * validate not null
     *
     * @param value value to validate
     */
    public static void validateNotNull(Object value, String err) {
        if (value == null)
            throw new AppException("500", err);
    }

    /**
     * validate null
     *
     * @param value value to validate
     */
    public static void validateNull(Object value, String err) {
        if (value != null)
            throw new AppException(err);
    }

    /**
     * validate not null
     *
     * @param value value to validate
     */
    public static void validateNotEmpty(Object value, String err) {
        validateNotNull(value, err);
        if (!value.getClass().equals(String.class))
            return;
        if (StringUtils.isEmpty((String) value))
            throw new AppException("500", err);
    }

    /**
     * validate format
     *
     * @param value   value
     * @param pattern regular expression
     */
    public static void validateFormat(String value, String pattern, String error) {
        if (value != null) {
            Pattern p = Pattern.compile(pattern);
            if (!p.matcher(value).matches())
                throw new AppException(error);
        }
    }

    /**
     * validate a == b, use equals method
     *
     * @param target current value
     * @param expect expecting value
     * @param error  msg when not equals
     */
    public static void validateEquals(Object target, Object expect, String error) {
        if (!Objects.equals(target, expect)) {
            throw new AppException(error);
        }
    }

    /**
     * if a == b throw exception
     *
     * @param target current value
     * @param expect expecting value
     * @param error  msg when not equals
     */
    public static void validateNotEquals(Object target, Object expect, String error) {
        if (Objects.equals(target, expect)) {
            throw new AppException(error);
        }
    }

    /**
     * validate if value in allowed value array
     * <p>
     * if object is not int one of allowed values, an exception of 'InvalidData' will be thrown
     *
     * @param value         value
     * @param allowedValues all possible values
     */
    public static void validateAllowed(Object value, Object[] allowedValues) {
        if (value == null)
            return;
        if (allowedValues != null && allowedValues.length > 0) {
            for (Object allowed : allowedValues) {
                if (value.equals(allowed))
                    return;
            }
        }
        throw new AppException(RES.getString(ERROR_INVALID_DATA));
    }

    /**
     * get nested property
     */
    public static Object getNestedProperty(Object obj, String property) {
        try {
            return PropertyUtils.getNestedProperty(obj, property);
        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | NestedNullException e) {
            return null;
        }
    }

    /**
     * 是否登录
     */
//    public static boolean isLogin() {
//        return securityContext.isLogin();
//    }

    /**
     * 获取当前用户
     */
//    public User getCurrentUser() {
//        return securityContext.getUserInfo();
//    }

    /**
     * 获取对应的字符串资源
     */
    public static String getResource(String resourceName) {
        return RES.getString(resourceName);
    }

    /**
     * 抛出非法数据的错误
     */
    public static void throwInvalidData() {
        throw new AppException(getResource(ERROR_INVALID_DATA));
    }

    /**
     * 抛出非法操作的错误
     */
    public static void throwInvalidOperation() {
        throw new AppException(getResource(ERROR_INVALID_OPERATION));
    }

    /**
     * 检查布尔值是否为true
     */
    public static boolean isTrue(Boolean b) {
        return isTrue(b, false);
    }

    /**
     * 检查布尔值是否为true
     */
    public static boolean isTrue(Boolean b, boolean nullAs) {
        return b == null ? nullAs : b.equals(true);
    }

    /**
     * 检查布尔值是否为false
     */
    public static boolean isFalse(Boolean b) {
        return isFalse(b, true);
    }

    /**
     * 检查布尔值是否为false
     */
    public static boolean isFalse(Boolean b, boolean nullAs) {
        return b == null ? !nullAs : b.equals(false);
    }

    /**
     * 获取布尔值
     */
    public static boolean bool(Boolean b, boolean nullAs) {
        return b == null ? nullAs : b;
    }

    /**
     * 检查布尔值是否相同
     */
    public static boolean isSame(Boolean b1, Boolean b2, boolean nullAs) {
        boolean bb1 = b1 == null ? nullAs : b1;
        boolean bb2 = b2 == null ? nullAs : b2;
        return bb1 == bb2;
    }
}
